package com.lemon.boot.common.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lemon.boot.common.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 李猛
 * @datetime 2024/2/7 0:41
 * @description 类对象
 */
@Slf4j
@Service
public class RedisServiceImpl implements RedisService {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean save(String key, Object value, long time, TimeUnit unit) {
        log.info("Redis缓存有时效的保存.save.key:{}", key);
        if (!StringUtils.hasText(key)) {
            return false;
        }
        try {
            redisTemplate.opsForValue().set(key, value, time, unit);
            return true;
        } catch (Exception e) {
            log.error("RedisServiceImpl.save.message:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public boolean save(String key, Object value, String time, TimeUnit unit) {
        return save(key, value, NumberUtil.parseLong(time), unit);
    }

    @Override
    public boolean save(String key, Object value) {
        log.info("Redis缓存保存.save.key:{}", key);
        if (!StringUtils.hasText(key)) {
            return false;
        }
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            log.error("RedisServiceImpl.save.message:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public boolean del(String key) {
        log.info("Redis缓存根据key删除数据.del.key:{}", key);
        if (!StringUtils.hasText(key)) {
            return false;
        }
        try {
            Boolean result = redisTemplate.delete(key);
            return Boolean.TRUE.equals(result);
        } catch (Exception e) {
            log.error("RedisServiceImpl.del.message:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public boolean dels(String... keys) {
        //1.判断 keys 是否为空
        if (keys == null || keys.length == 0) {
            return false;
        }
        log.info("Redis缓存根据key删除数据.dels:{}", Arrays.toString(keys));

        try {
            Long delete = redisTemplate.delete(Arrays.asList(keys));
            return delete != null && delete == keys.length;
        } catch (Exception e) {
            log.error("RedisServiceImpl.dels.message:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public <T> T get(String key, Class<T> tClass) {
        log.info("Redis缓存根据key获取数据.get.key:{}", key);
        if (!StringUtils.hasText(key)) {
            return null;
        }
        try {
            Object object = redisTemplate.opsForValue().get(key);
            if (Objects.isNull(object)) {
                return null;
            }
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.convertValue(object, tClass);
        } catch (Exception e) {
            log.error("RedisServiceImpl.get.message:{}", e.getMessage());
        }
        return null;
    }

    @Override
    public boolean has(String key) {
        log.info("Redis缓存是否存在key.hasKey.key:{}", key);
        if (!StringUtils.hasText(key)) {
            return false;
        }
        try {
            Boolean result = redisTemplate.hasKey(key);
            return result != null && result;
        } catch (Exception e) {
            log.error("RedisServiceImpl.has.message:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public boolean expire(String key, long time, TimeUnit unit) {
        log.info("Redis缓存根据key设置过期时间.expireByKey.key:{}", key);
        if (!StringUtils.hasText(key)) {
            return false;
        }
        try {
            Boolean result = redisTemplate.expire(key, time, unit);
            return Boolean.TRUE.equals(result);
        } catch (Exception e) {
            log.error("RedisServiceImpl.expire.message:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public boolean lockByTimes(String key, int times, int timeout, TimeUnit unit) {
        log.info("Redis缓存根据key,次数锁定key,key:{},times:{},timeout:{},unit:{}", key, times, timeout, unit);
        //1.判断 key 是否存在
        if (this.has(key)) {
            //2.判断输入的次数
            int value = this.get(key, Integer.class);
            if (value < times) {
                return this.save(key, value + 1, timeout, unit);
            } else {
                return false;
            }
        } else {
            return this.save(key, 1, timeout, TimeUnit.MINUTES);
        }
    }

    @Override
    public <T> Map<String, T> keys(String pattern, Class<T> tClass) {
        log.info("Redis缓存根据key获取key,value集合.keys.pattern:{}", pattern);
        if (!StringUtils.hasText(pattern)) {
            return new HashMap<>(0);
        }
        //1.获取所有的key
        Set<String> keys = redisTemplate.keys(pattern);
        if (CollectionUtils.isEmpty(keys)) {
            return new HashMap<>(0);
        }

        return keys.stream().collect(Collectors.toMap(key -> key, key -> this.get(key, tClass)));
    }
}
